using System;

namespace PDUConverter
{
    /// <summary>
    /// Represents an SMS-STATUS-REPORT PDU, a status report message.
    /// </summary>
    public class SmsStatusReportPdu : IncomingSmsPdu
    {
        private SmsTimestamp dischargeTime;
        private byte messageReference;
        private ParameterIndicator parameterIndicator;
        private string recipientAddress;
        private byte recipientAddressType;
        private SmsTimestamp scTimestamp;
        private MessageStatus status;

        /// <summary>
        /// Initializes a new <see cref="T:GsmComm.PduConverter.SmsStatusReportPdu" /> instance using default values.
        /// </summary>
        public SmsStatusReportPdu()
        {
            base._messageFlags = new SmsStatusReportMessageFlags();
            this.messageReference = 0;
            this.RecipientAddress = string.Empty;
            this.scTimestamp = SmsTimestamp.None;
            this.dischargeTime = SmsTimestamp.None;
            this.status = 0;
            this.parameterIndicator = null;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:GsmComm.PduConverter.SmsStatusReportPdu" /> class
        /// using the specified PDU string.
        /// </summary>
        /// <param name="pdu">The PDU string to convert.</param>
        /// <param name="includesSmscData">Specifies if the string contains
        /// SMSC data octets at the beginning.</param>
        /// <param name="actualLength">Specifies the actual PDU length, that is the length in bytes without
        /// the SMSC header. Set to -1 if unknown.</param>
        /// <remarks>
        /// <para>This constructor assumes that the string contains an <b>SMS-STATUS-REPORT</b>
        /// PDU data stream as specified
        /// by GSM 07.05.</para>
        /// </remarks>
        public SmsStatusReportPdu(string pdu, bool includesSmscData, int actualLength)
        {
            if (pdu == string.Empty)
            {
                throw new ArgumentException("pdu must not be an empty string.");
            }
            bool flag = actualLength >= 0;
            int num = actualLength;
            if (!flag || (num > 0))
            {
                int index = 0;
                if (includesSmscData)
                {
                    string str;
                    byte num3;
                    SmsPdu.DecodeSmscAddress(pdu, ref index, out str, out num3);
                    base.SetSmscAddress(str, num3);
                }
                base._messageFlags = new SmsStatusReportMessageFlags(BcdWorker.GetByte(pdu, index++));
                if (flag)
                {
                    num--;
                    if (num <= 0)
                    {
                        return;
                    }
                }
                this.messageReference = BcdWorker.GetByte(pdu, index++);
                SmsPdu.DecodeGeneralAddress(pdu, ref index, out this.recipientAddress, out this.recipientAddressType);
                if ((index * 2) >= pdu.Length)
                {
                    base.ProtocolID = 0x91;
                    base.DataCodingScheme = 0x89;
                    this.SCTimestamp = SmsTimestamp.None;
                    this.DischargeTime = SmsTimestamp.None;
                }
                else
                {
                    this.scTimestamp = new SmsTimestamp(pdu, ref index);
                    this.dischargeTime = new SmsTimestamp(pdu, ref index);
                    this.status = BcdWorker.GetByte(pdu, index++);
                    int num4 = BcdWorker.CountBytes(pdu);
                    if (index < num4)
                    {
                        this.parameterIndicator = new ParameterIndicator(BcdWorker.GetByte(pdu, index++));
                        if (this.parameterIndicator.Extension)
                        {
                            ParameterIndicator indicator;
                            do
                            {
                                int num5 = BcdWorker.CountBytes(pdu);
                                if (index >= num5)
                                {
                                    return;
                                }
                                indicator = new ParameterIndicator(BcdWorker.GetByte(pdu, index++));
                            }
                            while (indicator.Extension);
                        }
                        if (this.parameterIndicator.TP_PID)
                        {
                            base.ProtocolID = BcdWorker.GetByte(pdu, index++);
                        }
                        if (this.parameterIndicator.TP_DCS)
                        {
                            base.DataCodingScheme = BcdWorker.GetByte(pdu, index++);
                        }
                        if (this.parameterIndicator.TP_UDL)
                        {
                            byte num6;
                            byte[] buffer;
                            SmsPdu.DecodeUserData(pdu, ref index, out num6, out buffer);
                            base.SetUserData(buffer, num6);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Returns the relevant timestamp for the message.
        /// </summary>
        /// <returns>An <see cref="T:GsmComm.PduConverter.SmsTimestamp" /> containing the discharge time, the timestamp where
        /// the status in this report occurred.</returns>
        public override SmsTimestamp GetTimestamp()
        {
            return this.dischargeTime;
        }

        /// <summary>
        /// Sets the recipient address and type directly without attempting to
        /// autodetect the type.
        /// </summary>
        /// <param name="address">The recipient address</param>
        /// <param name="addressType">The address type</param>
        public void SetRecipientAddress(string address, byte addressType)
        {
            this.recipientAddress = address;
            this.recipientAddressType = addressType;
        }

        /// <summary>
        /// Converts the value of this instance into a string.
        /// </summary>
        /// <param name="excludeSmscData">If true, excludes the SMSC header.</param>
        /// <returns>The encoded string.</returns>
        /// <remarks>Not implemented, always throws an <see cref="T:System.NotImplementedException" />.</remarks>
        public override string ToString(bool excludeSmscData)
        {
            throw new NotImplementedException("SmsStatusReportPdu.ToString() not implemented.");
        }

        /// <summary>
        /// Gets or sets the parameter identifying the time associated with a
        /// particular TP-ST outcome.
        /// </summary>
        public SmsTimestamp DischargeTime
        {
            get
            {
                return this.dischargeTime;
            }
            set
            {
                this.dischargeTime = value;
            }
        }

        /// <summary>
        /// Gets the message flags.
        /// </summary>
        public SmsStatusReportMessageFlags MessageFlags
        {
            get
            {
                return (SmsStatusReportMessageFlags) base._messageFlags;
            }
        }

        /// <summary>
        /// Gets or sets the parameter identifying the previously submitted
        /// SMS-SUBMIT or an SMS-COMMAND.
        /// </summary>
        public byte MessageReference
        {
            get
            {
                return this.messageReference;
            }
            set
            {
                this.messageReference = value;
            }
        }

        /// <summary>
        /// Parameter indicating whether or not there are more messages to send.
        /// </summary>
        public bool MoreMessages
        {
            get
            {
                return this.MessageFlags.MoreMessages;
            }
            set
            {
                this.MessageFlags.MoreMessages = value;
            }
        }

        /// <summary>
        /// Gets or sets the parameter indicating the presence of any of the
        /// optional parameters which follow.
        /// </summary>
        public ParameterIndicator ParameterIndicator
        {
            get
            {
                return this.parameterIndicator;
            }
            set
            {
                this.parameterIndicator = value;
            }
        }

        /// <summary>
        /// Parameter indicating whether the previously submitted TPDU was an
        /// SMS-SUBMIT or an SMS-COMMAND.
        /// </summary>
        /// <remarks>
        /// <para>false = SMS-STATUS-REPORT is the result of a SMS-SUBMIT</para>
        /// <para>true = SMS-STATUS-REPORT is the result of a SMS-COMMAND</para>
        /// </remarks>
        public bool Qualifier
        {
            get
            {
                return this.MessageFlags.Qualifier;
            }
            set
            {
                this.MessageFlags.Qualifier = value;
            }
        }

        /// <summary>
        /// Gets or sets the address of the recipient of the previously
        /// submitted mobile originated short message.
        /// </summary>
        /// <remarks>
        /// <para>When setting the property, also the <see cref="P:GsmComm.PduConverter.SmsStatusReportPdu.RecipientAddressType" /> property
        /// will be set, attempting to autodetect the address type.</para>
        /// <para>When getting the property, the address may be extended with address-type
        /// specific prefixes or other chraracters.</para>
        /// </remarks>
        public string RecipientAddress
        {
            get
            {
                return base.CreateAddressOfType(this.recipientAddress, this.recipientAddressType);
            }
            set
            {
                byte num;
                string str;
                base.FindTypeOfAddress(value, out num, out str);
                this.recipientAddress = str;
                this.recipientAddressType = num;
            }
        }

        /// <summary>
        /// Gets the type of the recipient address.
        /// </summary>
        /// <remarks>
        /// <para>Represents the Type-of-Address octets for the recipient address of the PDU.</para>
        /// </remarks>
        public byte RecipientAddressType
        {
            get
            {
                return this.recipientAddressType;
            }
        }

        /// <summary>
        /// Gets or sets the parameter identifying time when the SC received
        /// the previously sent SMS-SUBMIT.
        /// </summary>
        public SmsTimestamp SCTimestamp
        {
            get
            {
                return this.scTimestamp;
            }
            set
            {
                this.scTimestamp = value;
            }
        }

        /// <summary>
        /// Gets or sets the parameter identifying the status of the previously
        /// sent mobile originated short message.
        /// </summary>
        public MessageStatus Status
        {
            get
            {
                return this.status;
            }
            set
            {
                this.status = value;
            }
        }

        /// <summary>
        /// Parameter indicating that the TP-UD field contains a Header.
        /// </summary>
        public bool UserDataHeaderPresent
        {
            get
            {
                return this.MessageFlags.UserDataHeaderPresent;
            }
            set
            {
                this.MessageFlags.UserDataHeaderPresent = value;
            }
        }
    }
}